package com.authsphere.bootstrap.mobile.handler;

import com.authsphere.common.result.ResponseResult;
import com.authsphere.common.result.ResponseResultUtils;
import com.authsphere.security.common.handler.AbstractResponseAuthenticationSuccessHandler;
import com.authsphere.security.token.common.AccessToken;
import com.authsphere.security.token.common.AuthenticationTokenServices;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @program: AuthSphere
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/26 20:06
 **/
public class AccessTokenResponseAuthenticationSuccessHandler extends AbstractResponseAuthenticationSuccessHandler {

    private static final Logger log = LoggerFactory.getLogger(AccessTokenResponseAuthenticationSuccessHandler.class);

    private static final String DELIMITER = ":";
    private final AuthenticationTokenServices authenticationTokenServices;

    public AccessTokenResponseAuthenticationSuccessHandler(AuthenticationTokenServices authenticationTokenServices) {
        this.authenticationTokenServices = authenticationTokenServices;
    }

    @Override
    protected Object extract(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        if (!authentication.isAuthenticated()) {
            throw new AuthenticationServiceException("认证失败");
        }
        AccessToken accessToken = authenticationTokenServices.createAccessToken(authentication, false);
        if (accessToken != null) {
            return ResponseResult.ofSuccess(encodeTokens(new String[]{accessToken.getSeriesId(), accessToken.getValue()}));
        } else {
            throw new AuthenticationServiceException("认证失败");
        }
    }

    /**
     * Inverse operation of decode
     *
     * @param tokens the tokens to be encoded.
     * @return base64 encoding of the tokens concatenated with the ":" delimiter.
     */
    protected String encodeTokens(String[] tokens) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tokens.length; i++) {
            sb.append(URLEncoder.encode(tokens[i], StandardCharsets.UTF_8));
            if (i < tokens.length - 1) {
                sb.append(DELIMITER);
            }
        }
        String value = sb.toString();
        sb = new StringBuilder(new String(Base64.getEncoder().encode(value.getBytes())));
        while (sb.charAt(sb.length() - 1) == '=') {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }
}
